﻿using HartConfigTool.HARTCommands.CMDs;
using HartConfigTool.SerialPortUtil;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading;
using System.Threading.Tasks;

namespace HartConfigTool.UI.MainUI
{
    public class PollingAddress : CMD0ReadUniqueIdentifier
    {
        TaskCompletionSource<bool> tcs;
        CancellationTokenSource cts;
        CancellationToken token;

        public PollingAddress(SerialPortsManager serialPortManager) : base(serialPortManager) 
        {
            tcs = new TaskCompletionSource<bool>();
            cts = new CancellationTokenSource();
            token = cts.Token;
        }

        protected override async Task SendCMDCode()
        {
            byte[] tempAry = new byte[16];
            byte[] cmdCodeBytes = StructToBytes<HARTCMD0ReadUniqueIdentifierStruct>(HARTCMD0ReadUniqueIdentifierCode);

            Array.Copy(cmdCodeBytes, 5, tempAry, 0, 4);
            cmdCodeBytes[cmdCodeBytes.Length - 1] = HARTProtocolV7.GetCRC(tempAry, (byte)4);

            serialPortManager.DebugMessage("[" + DateTime.Now + "]:-->" + HARTProtocolV7.HexToString(cmdCodeBytes) + "\r\n");

            await serialPortManager.SendCMD(cmdCodeBytes);
        }
        public override async Task ParseResponse(byte[] responseData)
        {
            await Task.Run(() =>
            {
                byte[] bytes = null;
                byte[] data = null;

                data = serialPortManager.GetRxBufferData();

                bytes = HARTProtocolV7.GetDataFrame(data);

                // Debug Message
                serialPortManager.DebugMessage("[" + DateTime.Now + "]:<--" + HARTProtocolV7.HexToString(data) + "\r\n");

                this.serialPortManager.RxDataClear();

            });
        }
        public async Task PollingAddressStart()
        {
            EventHandler taskCompeletionHandler = (s, e) => tcs.TrySetResult(true);
            EventHandler cancellationTokenHandler = (s, e) => cts.Cancel();

            try
            {
                serialPortManager.CommandCompleted += taskCompeletionHandler;
                serialPortManager.CommandCompleted += cancellationTokenHandler;

                for (byte i = 0; i < 16; i++)
                {
                    if (token.IsCancellationRequested)
                    {
                        return;
                    }

                    HARTCMD0ReadUniqueIdentifierCode.address = (byte)((HARTCMD0ReadUniqueIdentifierCode.address & 0xf0) | i);
                    await SendCMDCode();

                    var timeoutTask = Task.Delay(TimeSpan.FromSeconds(2), cts.Token);
                    var responseTask = tcs.Task;

                    var compeletedTask = await Task.WhenAny(timeoutTask, responseTask);

                    serialPortManager.DebugMessage("[" + DateTime.Now + $"]: {i}\r\n");
                }
            }
            finally
            {
                serialPortManager.CommandCompleted -= taskCompeletionHandler;
                serialPortManager.CommandCompleted -= cancellationTokenHandler;
            }
        }
    }
}
